#!usr/bin/env python3
# -*- coding: utf-8 -*-
#cookbook 第一章练习代码
from collections import deque
#3.2 从一个迭代对象中解压出特定的数据赋值给多个变量
record = ["dave","jonh",100,50,30,"good","3"]
_,_,*lastAll = record;
print(lastAll) #得到除了前面两个元素的list
 
 #利用解压的*号解压法实现递归
def sum(nums):
     head,*tail = nums
     return head+sum(tail) if tail else head;

print(sum([1,2,3,4,5]))

head, *tail = [1]
print("tail",tail)
if tail!=None:
    print("Hello tail") # 2017年3月31日18:08:44 16页

dqArr = deque([1,2,3,4,5],3) #前面的参数是初始化的可迭代对象，后面是长度
print(dqArr) #根据长度先进先出 所以输出的是 deque([3, 4, 5], maxlen=3)

dqArr1 = deque([1,2,3,4]) #声明一个不限长度的队列
dqArr1.appendleft(5) #在队列的左边加一个元素 就是在开头加一个元素
lastEle = dqArr1.pop() #删除并返回最后一个元素(
print('lastEle',lastEle)
firstEel = dqArr1.popleft() #删除左边的元素 也就是第一个元素

#怎样从一个集合中获得最大或者最小的N 个元素列表？
import heapq

nums = [12,43,5,734,7,4,445,3232]
largest = heapq.nlargest(3,nums) #获取列表中最大的三个数,从大到小降序 牛掰的函数 方便快捷（查询的元素个数较小时才用这个函数比较快）
print('largest',largest)
smalest = heapq.nsmallest(4,nums) #获取列表中最小的三个数,从小到大升序 牛掰的函数 方便快捷 （查询的元素个数较小时才用这个函数比较快）
print("smalest=",smalest)

print('heapq.heappop=',heapq.heappop(nums))
heapq.heapify(nums) #对集合进行堆排序,该排序函数只是确保第一个元素是最小的 不会全部排序
print('heapq.heappop=',heapq.heappop(nums),nums) #始终返回最小的一个元素
heapq.heapify(nums) 
print('heapq.heappop=',heapq.heappop(nums),nums) #2017年4月6日16:08:11 20 p20

from   collections import defaultdict,OrderedDict

d = defaultdict(list) #该字典内所有的key的值都是list对象 就算key不存在也会默认创建 
d['a'].append(1)
d['a'].append(2)

print(d)
print(d['b']) #就算key不存在也会默认创建 

print(list(zip(d.values(),d.keys())))

prices = {
    "37Game":21.9,
    "baidu":101.9,
    "sina":92.9,
    "sohu":76.9,
}

m = min(prices,key=lambda k:prices[k])
print(m)

#zip函数会把传入的多个列表取对应下标的元素组合成一个set 返回一个迭代对象 每个元素是一个set 迭代最大长度是传入的list长度最小的那个长度

zIter=zip(prices.values(),prices.keys())
print(zIter,zIter.__next__(),min(zIter))
 
zIter=zip([12,13,14],['a','b'])
print(zIter,list(zIter))

d1 = {
    'k1':10,
    'k2':11,
    'k3':12,
}

d2 = {
    'k1':10,
    'k2':11,
    'k4':13,
    'k5':14,
}

print((d1.keys() & d2.keys()))

d3 = {key:d2[key] for key in d2.keys()-('k1','k4')} #通过列表推导式，删除字典中指定的多个键值，组成一个新的字典
print(d3)

# 通过生成器删除列表中重复的元素

def dedupe(items,key=None):
    seen = set()
    for v in items:
        val = v if key is None else key(v)
        if val not in seen:
            yield v
            seen.add(val)

print(list(dedupe([1,2,3,1,4,2,5])))

#命名切片
arr1 = [1,2,3,4,5,6,7,8]
sliceObj = slice(2,5,3) #创建一个切片对象

print(arr1[sliceObj],sliceObj.start,sliceObj.stop,sliceObj.step)

import sys
print(sys.version)
from collections import Counter

#找出集合中出现次数最多的元素

words=['a','b','c','d','a','c','c','a','b']
word_count=Counter(words) #得到一个counter对象，是一个哈希表，元素是下标，值是元素出现的次数
print(word_count,type(word_count),word_count.most_common(2))  #most_common列出出现次数最多的前N个元素

rows = [
{'address': '5412 N CLARK', 'date': '07/01/2012'},
{'address': '5148 N CLARK', 'date': '07/04/2012'},
{'address': '5800 E 58TH', 'date': '07/02/2012'},
{'address': '2122 N CLARK', 'date': '07/03/2012'},
{'address': '5645 N RAVENSWOOD', 'date': '07/02/2012'},
{'address': '1060 W ADDISON', 'date': '07/02/2012'},
{'address': '4801 N BROADWAY', 'date': '07/01/2012'}
]

# 排序和分组
from operator import itemgetter,attrgetter
from itertools import groupby
rows.sort(key=itemgetter('date')) #根据date字段排序

print(groupby(rows,key=itemgetter('date'))) # 排序后分组，对于分组都是要先排序才有意义  groupby是列出列表中连续相同的来分组

for date ,items in groupby(rows,key=itemgetter('date')):
    print(date,list(items),type(items))

# 命名元组

from collections import namedtuple

Subable = namedtuple('Subable',['addr','joined']) # 相当于创建一个类 但是它又是和元组一样可以和元组交互的

sub = Subable('lianJianng','20170320')

a,b=sub # 拆值，把 addr和joined属性赋值给a b
print(a,b)

# sub.addr = 'gz' # 命名元组的字段值不能直接修改，这里会报错
sub = sub._replace(addr="gz") #相当于重新创建一个元组 用新值代替旧值
print(sub)

#合并多个字典或映射
from collections import ChainMap

a = {'x':1,'z':2}
b = {'y':3,'z':4}

cm = ChainMap(a,b) # 把多个字典合并成一个在逻辑上是一个字典的集合 实际上是一个ChainMap实例 ，但是它都具有几乎所有字典的操作
print(cm,type(cm))

print(cm['z'])  # z的键值始终是第一次出现的字典的键值，更改的话也只是影响第一个出现的字典




